package com.yunshipei.core.manager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.text.TextUtils;

import com.yunshipei.core.BuildConfig;
import com.yunshipei.core.common.ContentValues;
import com.yunshipei.core.common.XCloudException;
import com.yunshipei.core.common.db.DBManager;
import com.yunshipei.core.model.AdapterPacInfo;
import com.yunshipei.core.model.ConfigInfo;
import com.yunshipei.core.model.XCloudRuntimeModel;
import com.yunshipei.core.net.EnterClient;
import com.yunshipei.core.net.ServiceApi;
import com.yunshipei.core.utils.FileUtils;
import com.yunshipei.core.utils.StringUtils;
import com.yunshipei.core.utils.YspLogUtils;

import org.chromiun.net.GURLUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.reactivestreams.Publisher;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.FormBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import static com.yunshipei.core.manager.AdapterPkgHandler.TABLE_RUNTIME_ENGINE_INFO;

final class XCloudDataHandler {

    static final String SP_KEY_ADAPTER_PKG_CONFIG_NAME = "enter_adapter_config_info";
    static final String SP_KEY_LAST_OLD_HOME_PAGE_VERSION = "sp_enterplorer_last_old_home_page_version";
    static final String SP_KEY_RUNTIME_ENC_CONFIG_NAME = "sp_enterplorer_secret_key";
    static final String KEY_ADAPTER_CFG = "appId";
    static final String VALUE_ADAPTER_CFG = "version";
    static final String VALUE_ADAPTER_NAME = "pac_name";
    static final String KEY_RUNTIME_VERSION = "runtime_version";
    static final String VALUE_RUNTIME_ENC_MANAGER_SERVER = "enc_manager_server";
    private static final String HUB_SERVER = "https://hub.enterplorer.com";
    private static final String HUB_TEST_SERVER = "https://hubtest.enterplorer.com";


    private Context mContext;
    private String mManagerServer;
    private JSONObject mResultData;
    private String mAppFilePath = "";
    private String mLastOldHomePageVersion = "";

    private Map<String, AdapterPacInfo> mLastAdapterVersionMap = new HashMap<>();
    private Map<String, AdapterPacInfo> mAdapterVersionMap = new HashMap<>();
    private SharedPreferences mPreferences;
    private boolean isCachedLoginData = false;

    XCloudDataHandler(Context context, String managerServer, JSONObject resultData, boolean isCachedLoginData) {
        this.mContext = context;
        this.mManagerServer = managerServer;
        this.mResultData = resultData;
        this.mAppFilePath = context.getFilesDir().getPath();
        this.mPreferences = context.getSharedPreferences(XCloudSDKManager.SP_CONFIG_FILE_NAME, Context.MODE_PRIVATE);
        this.isCachedLoginData = isCachedLoginData;
        if (!isCachedLoginData) {
            String adapterConfigInfo = mPreferences.getString(SP_KEY_ADAPTER_PKG_CONFIG_NAME, "");
            if (!TextUtils.isEmpty(adapterConfigInfo)) {
                try {
                    JSONArray adapterCfgArray = new JSONArray(adapterConfigInfo);
                    int len = adapterCfgArray.length();
                    for (int i = 0; i < len; i++) {
                        JSONObject adapterCfgObj = adapterCfgArray.optJSONObject(i);
                        if (adapterCfgObj != null) {
                            String key = adapterCfgObj.optString(KEY_ADAPTER_CFG);
                            String value = adapterCfgObj.optString(VALUE_ADAPTER_CFG);
                            String name = adapterCfgObj.optString(VALUE_ADAPTER_NAME, "");
                            if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                                mLastAdapterVersionMap.put(key, new AdapterPacInfo(value, name));
                            }
                        }
                    }
                } catch (JSONException ignored) {
                }
            }
            this.mLastOldHomePageVersion = mPreferences.getString(SP_KEY_LAST_OLD_HOME_PAGE_VERSION, "");
        }
    }

    Flowable<JSONObject> start() {
        if (isCachedLoginData) {
            return resultCacheDataFlowable();
        }
        return preparePkgDownloadPck().flatMap(new Function<List<Flowable<Boolean>>, Publisher<JSONObject>>() {
            @Override
            public Publisher<JSONObject> apply(List<Flowable<Boolean>> observables) throws Exception {
                final int size = observables.size();
                if (size == 0) {
                    return resultDataFlowable();
                } else {
                    return Flowable.zip(observables, new Function<Object[], Boolean>() {
                        @Override
                        public Boolean apply(Object[] objects) throws Exception {
                            return objects.length == size;
                        }
                    }).flatMap(new Function<Boolean, Publisher<JSONObject>>() {
                        @Override
                        public Publisher<JSONObject> apply(Boolean aBoolean) throws Exception {
                            if (aBoolean) {
                                return resultDataFlowable();
                            }
                            return Flowable.error(new XCloudException("未知错误..."));
                        }
                    });
                }
            }
        });
    }

    //准备适配包和运行时相关数据
    private Flowable<List<Flowable<Boolean>>> preparePkgDownloadPck() {
        return Flowable.create(new FlowableOnSubscribe<List<Flowable<Boolean>>>() {
            @Override
            public void subscribe(FlowableEmitter<List<Flowable<Boolean>>> e) throws Exception {
                List<Flowable<Boolean>> observables = new ArrayList<>();
                JSONObject dataObject = mResultData.optJSONObject("data");
                JSONObject companyObject = null;
                if (dataObject != null) {
                    companyObject = dataObject.optJSONObject("company");
                }
                if (dataObject != null && companyObject != null) {
                    //运行时包下载数据处理
                    String encManagerServer = companyObject.optString("managerServer");
                    String companyId = companyObject.optString("companyId");
                    JSONArray runtimeArray = companyObject.optJSONArray("runtimes");
                    int runtimePackageCount = 0;
                    if (runtimeArray != null) {
                        runtimePackageCount = runtimeArray.length();
                    }
                    if (runtimePackageCount > 0) {
                        String companyName = companyObject.optString("website");
                        boolean isManagerRuntime = companyObject.optBoolean("useManager", false);
                        String runtimeDownloadUrl = isManagerRuntime ? mManagerServer : generateHubServer(companyName);
                        YspLogUtils.d("runtime download url:" + runtimeDownloadUrl);
                        ServiceApi serviceApi = new Retrofit.Builder().baseUrl(runtimeDownloadUrl).client(isManagerRuntime ? EnterClient.getInstances().getManagerClient() : EnterClient.getInstances().getHubClient()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(ServiceApi.class);
                        for (int i = 0; i < runtimePackageCount; i++) {
                            JSONObject runtimeObj = runtimeArray.optJSONObject(i);
                            if (runtimeObj != null) {
                                if (userLocalRuntime(runtimeObj)) continue;
                                Flowable<Boolean> observable = generateRuntimeFlowable(companyId, serviceApi, runtimeObj, encManagerServer);
                                if (observable != null) {
                                    observables.add(observable);
                                }
                            }
                        }
                    } else {
                        YspLogUtils.d("运行时数目为0");
                    }

                    //适配包下载数据处理,需要兼容旧版适配包，旧版适配包和九宫格首页包是在一起的
                    JSONObject incrementalVersionsObject = null;
                    JSONObject dataJsAppsObject = dataObject.optJSONObject("datajsApps");
                    if (dataJsAppsObject != null) {
                        incrementalVersionsObject = dataJsAppsObject.optJSONObject("incrementalVersions");
                    }
                    if (incrementalVersionsObject != null) {
                        mLastOldHomePageVersion = "";
                        //增量更新的适配包方案
                        JSONArray adapterPackageArray = incrementalVersionsObject.optJSONArray("applications");
                        int adapterPackageCount = 0;
                        if (adapterPackageArray != null) {
                            adapterPackageCount = adapterPackageArray.length();
                        }
                        if (adapterPackageCount > 0) {
                            ServiceApi serviceApi = new Retrofit.Builder().client(EnterClient.getInstances().getManagerClient()).baseUrl(mManagerServer).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(ServiceApi.class);
                            for (int i = 0; i < adapterPackageCount; i++) {
                                JSONObject adapterObject = adapterPackageArray.optJSONObject(i);
                                if (adapterObject != null) {
                                    Flowable<Boolean> observable = generateAdapterPackageFlowable(serviceApi, adapterObject);
                                    if (observable != null) {
                                        observables.add(observable);
                                    }
                                }
                            }
                        } else {
                            YspLogUtils.d("适配包数目为0");
                        }
                    } else {
                        //旧版首页包和适配包在一起的方案
                        String homePage = dataObject.optString("homepage");
                        if (!TextUtils.isEmpty(homePage)) {
                            final String fileName = homePage.substring(homePage.lastIndexOf("/") + 1).replace(".zip", "");
                            File authFile = new File(mAppFilePath + File.separator + ContentValues.APP_WEB_ROOT_PATH, mLastOldHomePageVersion);
                            if (TextUtils.isEmpty(mLastOldHomePageVersion) || !fileName.equals(mLastOldHomePageVersion) || !authFile.exists()) {
                                //需要重新下载该包
                                Flowable<Boolean> observable = generateOldHomePagePackageFlowable(homePage, fileName);
                                observables.add(observable);
                            }
                        } else {
                            YspLogUtils.d("不使用增量更新方式，但是也不存在旧版适配包");
                        }
                    }
                    e.onNext(observables);
                } else {
                    e.onError(new XCloudException("接口缺少必要字段company"));
                }
            }
        }, BackpressureStrategy.BUFFER);
    }

    //下载解压运行时
    private Flowable<Boolean> generateRuntimeFlowable(String companyId, ServiceApi serviceApi, JSONObject runtimeObj, final String encManagerServer) {
        final String primaryVersion = runtimeObj.optString("primaryVersion");
        final String runtimeVersion = runtimeObj.optString("runtimeVersion");
        final boolean isSpecificVersion = runtimeObj.optBoolean("isSpecificVersion");
        final XCloudRuntimeModel xCloudRuntimeModel = new XCloudRuntimeModel(primaryVersion, runtimeVersion, isSpecificVersion);
        final String rootPath = mAppFilePath + File.separator + ContentValues.APP_ENGINE_ROOT_PATH;
        RequestBody requestBody = generateRuntimeDownloadRequestBody(companyId, xCloudRuntimeModel, encManagerServer);
        if (requestBody != null) {
            final String fileName = isSpecificVersion ? runtimeVersion : primaryVersion;
            final String tempFileName = rootPath + File.separator + fileName + "_temp";
            return serviceApi.runtimeDownloadRequest(requestBody).flatMap(new Function<Response<ResponseBody>, Publisher<Boolean>>() {
                @Override
                public Publisher<Boolean> apply(Response<ResponseBody> response) throws Exception {
                    String errorMsg;
                    int code = response.code();
                    if (200 == code) {
                        InputStream inputStream = response.body().byteStream();
                        boolean unZipSuccess = FileUtils.unZipStream(inputStream, tempFileName);
                        if (unZipSuccess) {
                            File oldFile = new File(rootPath + File.separator + fileName);
                            FileUtils.deletePathReal(oldFile.getPath());
                            File newFile = new File(tempFileName);
                            boolean renameSuccess = newFile.renameTo(oldFile);
                            if (renameSuccess) {
                                return Flowable.just(true);
                            } else {
                                errorMsg = String.format("运行时%s保存失败", fileName);
                            }
                        } else {
                            errorMsg = String.format("运行时%s解压失败", fileName);
                        }
                    } else if (204 == code && !isSpecificVersion) {
                        return Flowable.just(true);
                    } else {
                        YspLogUtils.d(String.format("运行时%s请求出错，错误状态码:" + code + "," + response.toString(), fileName));
                        errorMsg = String.format("运行时%s请求出错，错误状态码:" + code, fileName);
                    }
                    return Flowable.error(new XCloudException(errorMsg));
                }
            }).flatMap(new Function<Boolean, Publisher<Boolean>>() {
                @Override
                public Publisher<Boolean> apply(Boolean aBoolean) throws Exception {
                    //将encManagerServer对应到运行时
                    //存储当前运行时对应的解密Manager服务器地址
                    DBManager dbManager = DBManager.getInstance();
                    SQLiteDatabase db = dbManager.openDB(mContext);
                    db.beginTransaction();
                    android.content.ContentValues contentValues = new android.content.ContentValues();
                    contentValues.put(KEY_RUNTIME_VERSION, fileName);
                    contentValues.put(VALUE_RUNTIME_ENC_MANAGER_SERVER, encManagerServer);
                    Cursor c2 = db.query(TABLE_RUNTIME_ENGINE_INFO, new String[]{VALUE_RUNTIME_ENC_MANAGER_SERVER}, KEY_RUNTIME_VERSION + "=?", new String[]{fileName}, null, null, null);
                    if (c2.moveToNext()) {
                        db.update(TABLE_RUNTIME_ENGINE_INFO, contentValues, KEY_RUNTIME_VERSION + "=?", new String[]{fileName});
                    } else {
                        db.insert(TABLE_RUNTIME_ENGINE_INFO, null, contentValues);
                    }
                    c2.close();
                    db.setTransactionSuccessful();
                    db.endTransaction();
                    dbManager.closeDB();
                    return Flowable.just(true);
                }
            }).doOnError(new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    FileUtils.deletePathReal(tempFileName);
                    YspLogUtils.d(String.format("运行时%s处理异常：exception——>" + throwable.toString(), fileName));
                }
            }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
        }
        return null;
    }

    //下载解压适配包
    private Flowable<Boolean> generateAdapterPackageFlowable(ServiceApi serviceApi, final JSONObject adapterObject) {
        final String version = adapterObject.optString("version");
        final String appId = adapterObject.optString("appId");
        final String downloadUrl = adapterObject.optString("downloadUrl");
        final String adapterPacName = StringUtils.getZipPkgDownloadUrlFileName(downloadUrl);
        if (!TextUtils.isEmpty(version) && !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(downloadUrl) && !TextUtils.isEmpty(adapterPacName)) {
            mAdapterVersionMap.put(appId, new AdapterPacInfo(version, adapterPacName));
            final String rootPath = mAppFilePath + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH;
            File authFile = new File(mAppFilePath + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH, adapterPacName);
            boolean authFileStatus = authFile.exists() && authFile.listFiles() != null && authFile.listFiles().length > 0;
            if (!mLastAdapterVersionMap.containsKey(appId) || !version.equals(mLastAdapterVersionMap.get(appId).getVersion()) || !authFileStatus) {
                final String tempFileName = rootPath + File.separator + adapterPacName + "_temp";
                return serviceApi.commonDownload(downloadUrl).flatMap(new Function<Response<ResponseBody>, Publisher<Boolean>>() {
                    @Override
                    public Publisher<Boolean> apply(Response<ResponseBody> response) throws Exception {
                        String errorMsg;
                        int code = response.code();
                        if (200 == code) {
                            InputStream inputStream = response.body().byteStream();
                            boolean unZipSuccess = FileUtils.unZipStream(inputStream, tempFileName);
                            if (unZipSuccess) {
                                File oldFile = new File(rootPath + File.separator + adapterPacName);
                                FileUtils.deletePathReal(oldFile.getPath());
                                File newFile = new File(tempFileName);
                                boolean renameSuccess = newFile.renameTo(oldFile);
                                if (renameSuccess) {
                                    return Flowable.just(true);
                                } else {
                                    errorMsg = String.format("适配包%s保存失败", adapterPacName);
                                }
                            } else {
                                errorMsg = String.format("适配包%s解压失败", adapterPacName);
                            }
                        } else {
                            YspLogUtils.d(String.format("适配包%s下载请求失败，状态码：" + code + "," + response.toString(), adapterPacName));
                            errorMsg = String.format("适配包%s下载请出错，状态码：" + code, adapterPacName);
                        }
                        return Flowable.error(new XCloudException(errorMsg));
                    }
                }).doOnError(new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        FileUtils.deletePathReal(tempFileName);
                        YspLogUtils.d(String.format("适配包%s处理异常：exception——>" + throwable.toString(), adapterPacName));
                    }
                }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
            }
        }
        return null;
    }

    //下载解压旧版首页包和适配包
    private Flowable<Boolean> generateOldHomePagePackageFlowable(String homePage, final String fileName) {
        final String rootPath = mAppFilePath + File.separator + ContentValues.APP_WEB_ROOT_PATH;
        ServiceApi serviceApi = new Retrofit.Builder().client(EnterClient.getInstances().getManagerClient()).baseUrl(mManagerServer).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(ServiceApi.class);
        final String tempFilePath = rootPath + File.separator + fileName + "_temp";
        return serviceApi.commonDownload(homePage).flatMap(new Function<Response<ResponseBody>, Publisher<Boolean>>() {
            @Override
            public Publisher<Boolean> apply(Response<ResponseBody> response) throws Exception {
                String errorMsg;
                int code = response.code();
                if (200 == code) {
                    InputStream inputStream = response.body().byteStream();
                    boolean unZipSuccess = FileUtils.unZipStream(inputStream, tempFilePath);
                    if (unZipSuccess) {
                        File oldFile = new File(rootPath + File.separator + fileName);
                        FileUtils.deletePathReal(oldFile.getPath());
                        FileUtils.deletePathReal(rootPath + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH);
                        File newFile = new File(tempFilePath);
                        boolean renameSuccess = newFile.renameTo(oldFile);
                        if (renameSuccess) {
                            //需要移动xcloud2json文件夹的位置
                            boolean copySuccess = true;
                            File fromFile = new File(oldFile.getPath() + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH);
                            File[] fromFiles = fromFile.listFiles();
                            if (fromFile.exists() && fromFile.isDirectory() && fromFiles != null && fromFiles.length > 0) {
                                copySuccess = FileUtils.copyFolder(fromFile.getPath(), rootPath + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH);
                                FileUtils.deleteFile(fromFile);
                            }
                            if (copySuccess) {
                                return Flowable.just(true);
                            } else {
                                FileUtils.deletePathReal(oldFile.getPath());
                                FileUtils.deletePathReal(rootPath + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH);
                                errorMsg = "首页包适配包配置出错";
                            }
                        } else {
                            errorMsg = "首页包适配包保存失败";
                        }
                    } else {
                        errorMsg = "首页包适配包解压出错";
                    }
                } else {
                    YspLogUtils.d("旧版适配包下载请求失败，状态码：" + code + "," + response.toString());
                    errorMsg = "适配包下载请求出错,状态码:" + code;
                }
                return Flowable.error(new XCloudException(errorMsg));
            }
        }).doOnError(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                FileUtils.deletePathReal(tempFilePath);
                YspLogUtils.d(String.format("首页适配包%s处理异常：exception——>" + throwable.toString(), fileName));
            }
        }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
    }

    //生成hub地址，如果使用公网的hub，则可以手动配置hub地址，为测试留的后门
    private String generateHubServer(String companyName) {
        if (BuildConfig.DEBUG) {
            File file = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "_ysp_hub_server.txt");
            if (file.exists()) {
                String server = FileUtils.readFile(file.getPath());
                if (!TextUtils.isEmpty(server)) {
                    return server.trim();
                }
            }
        }
        return TextUtils.isEmpty(companyName) ? HUB_SERVER : ((companyName.startsWith("ysptest-") || companyName.startsWith("www.ysptest-")) ? HUB_TEST_SERVER : HUB_SERVER);
    }

    /**
     * 运行时下载请求参数处理，不同的参数对应不同的下载方式
     * 逻辑：
     * 1、如果是特殊版本，则判断本地是否有特殊版本，如果有则不去请求，如果没有或者和服务器返回到运行时版本不一致，则重新下载覆盖旧的
     * 2、如果不是特殊版本，则是几+的版本，去本地几加的版本中读取版本号，传给服务器，如果服务器返回204，则本地几+的版本是最新版本，如果返回200，则需要替换几+的版本
     */
    private RequestBody generateRuntimeDownloadRequestBody(String companyId, XCloudRuntimeModel runtimeInfo, String encManagerServer) {
        final String COMPANY_ID = "companyId";
        final String SOURCE = "source";
        final String PRIMARY_VERSION = "primaryVersion";
        final String CURRENT_VERSION = "currentVersion";
        final String RUNTIME_VERSION = "runtimeVersion";
        final String SPECIFIC_VERSION = "specificVersion";

        FormBody.Builder builder = new FormBody.Builder();
        builder.add(COMPANY_ID, companyId);
        builder.add(SOURCE, "mobile");

        String primaryVersion = runtimeInfo.getPrimaryVersion();
        String runtimeVersion = runtimeInfo.getRuntimeVersion();

        int index = runtimeVersion.indexOf("-");
        if (index != -1) {
            runtimeInfo.setSpecificVersion(true);
        }

        String runtimeRootPath = mAppFilePath + File.separator + ContentValues.APP_ENGINE_ROOT_PATH;
        //是spec版本，文件夹以runtimeVersion的版本命名
        if (runtimeInfo.isSpecificVersion()) {
            //判断本地是不是存在这个版本的运行时
            File pFile = new File(runtimeRootPath, runtimeVersion);
            if (pFile.exists() && pFile.isDirectory() && pFile.length() > 0) {
                String encServer = getRuntimeEncManagerServer(runtimeVersion);
                if (!TextUtils.isEmpty(encServer) && encServer.equals(encManagerServer)) {
                    return null;
                }
            }
            builder.add(PRIMARY_VERSION, primaryVersion);
            builder.add(SPECIFIC_VERSION, runtimeVersion);
            return builder.build();
        } else {
            //不是special版本，以primaryVersion的版本命名
            File pFile = new File(runtimeRootPath, primaryVersion);
            File[] pFileLists = pFile.listFiles();
            if (!pFile.exists() || pFileLists == null || pFileLists.length == 0) {
                builder.add(PRIMARY_VERSION, primaryVersion);
                return builder.build();
            }

            //有1.+或2.+带+号的运行时，则将本地存在的version拼接在primary版本后面下载
            for (File prFile : pFileLists) {
                if (prFile.isDirectory()) continue;
                if (prFile.getName().equals("package.json")) {
                    String packageStr = FileUtils.readFile(prFile.getAbsolutePath());
                    try {
                        JSONObject jsonObject = new JSONObject(packageStr);
                        String version = jsonObject.optString("version");
                        builder.add(PRIMARY_VERSION, primaryVersion);
                        if (!TextUtils.isEmpty(version)) {
                            //此处是为了兼容旧版运行时与新版运行时过渡问题
                            for (File tempFile : pFileLists) {
                                if (tempFile.getName().endsWith(".enc")) {
                                    String encServer = getRuntimeEncManagerServer(primaryVersion);
                                    if (!TextUtils.isEmpty(encServer) && encServer.equals(encManagerServer)) {
                                        builder.add(RUNTIME_VERSION, runtimeVersion);
                                        builder.add(CURRENT_VERSION, version);
                                        return builder.build();
                                    }
                                }
                            }
                        }
                        return builder.build();
                    } catch (JSONException e) {
                        return builder.add(PRIMARY_VERSION, primaryVersion).build();
                    }
                }
            }
            return builder.add(PRIMARY_VERSION, primaryVersion).build();
        }
    }

    private String getRuntimeEncManagerServer(String runtimeVersion) {
        //查询一下该版本运行时对应的加密字段managerServer是不是一样，不一样也需要重新下载
        DBManager dbManager = DBManager.getInstance();
        SQLiteDatabase db = dbManager.openDB(mContext);
        Cursor cursor = db.query(TABLE_RUNTIME_ENGINE_INFO, new String[]{VALUE_RUNTIME_ENC_MANAGER_SERVER}, KEY_RUNTIME_VERSION + "=?", new String[]{runtimeVersion}, null, null, null);
        String encServer = "";
        while (cursor.moveToNext()) {
            encServer = cursor.getString(0);
        }
        cursor.close();
        dbManager.closeDB();
        return encServer;
    }

    //运行时适配包处理完毕后做适配数据的初始化工作
    private Flowable<JSONObject> resultDataFlowable() {
        return Flowable.create(new FlowableOnSubscribe<JSONObject>() {
            @SuppressLint("ApplySharedPref")
            @Override
            public void subscribe(FlowableEmitter<JSONObject> e) throws Exception {
                //删除本次接口中没有的，但是本地存在的旧的适配包
                Set<Map.Entry<String, AdapterPacInfo>> currentEntrySet = mAdapterVersionMap.entrySet();
                for (Map.Entry<String, AdapterPacInfo> entry : currentEntrySet) {
                    String key = entry.getKey();
                    if (mLastAdapterVersionMap.containsKey(key)) {
                        mLastAdapterVersionMap.remove(key);
                    }
                }
                Set<Map.Entry<String, AdapterPacInfo>> tempEntrySet = mLastAdapterVersionMap.entrySet();
                for (Map.Entry<String, AdapterPacInfo> entry : tempEntrySet) {
                    String name = entry.getValue().getPacName();
                    if (!TextUtils.isEmpty(name)) {
                        FileUtils.deletePathReal(mAppFilePath + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + name);
                    }
                }
                //初始化适配数据到内存
                JSONObject dataObject = mResultData.optJSONObject("data");
                JSONObject companyObject = null;
                if (dataObject != null) {
                    companyObject = dataObject.optJSONObject("company");
                }
                if (dataObject != null && companyObject != null) {
                    String companyId = companyObject.optString("companyId");
                    String created = companyObject.optString("created");
                    String encManagerServer = companyObject.optString("managerServer");
                    boolean privateDeployment = companyObject.optBoolean("privateDeployment");
                    String webSite = companyObject.optString("website");
                    JSONArray adapterPackageInfoArray = new JSONArray();
                    Set<Map.Entry<String, AdapterPacInfo>> entrySet = mAdapterVersionMap.entrySet();
                    for (Map.Entry<String, AdapterPacInfo> entry : entrySet) {
                        String key = entry.getKey();
                        AdapterPacInfo value = entry.getValue();
                        adapterPackageInfoArray.put(new JSONObject().put(KEY_ADAPTER_CFG, key).put(VALUE_ADAPTER_CFG, value.getVersion()).put(VALUE_ADAPTER_NAME, value.getPacName()));
                    }
                    String encDataStr = new JSONObject().put("filepath", mAppFilePath + File.separator).put("_id", companyId).put("created", created).put("managerServer", encManagerServer).put("privateDeployment", privateDeployment).put("website", webSite).toString();
                    mPreferences.edit().putString(SP_KEY_RUNTIME_ENC_CONFIG_NAME, encDataStr).putString(SP_KEY_ADAPTER_PKG_CONFIG_NAME, adapterPackageInfoArray.toString()).putString(SP_KEY_LAST_OLD_HOME_PAGE_VERSION, mLastOldHomePageVersion).commit();

                    String token = dataObject.optString("deviceToken", "");
                    int validCount = dataObject.optInt("validCount", 0);
                    long timestamp = dataObject.optLong("timestamp", 0);
                    String sdkSum = dataObject.optString("sdk_sum", "");
                    String uuid = dataObject.optString("uuid", "");
                    if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(sdkSum) && !TextUtils.isEmpty(uuid) && validCount != 0 && timestamp != 0) {
                        String sdkSumStr = new JSONObject().put("token", token).put("count", validCount).put("timestamp", timestamp).put("sdk_sum", sdkSum).put("deviceId", uuid).toString();
                        String checkSum = GURLUtils.checkSum(sdkSumStr);
                        if (TextUtils.isEmpty(checkSum) || !"check success".equalsIgnoreCase(checkSum)) {
                            e.onError(new XCloudException("sdkSum check failed：" + checkSum));
                        }
                        YspLogUtils.d("checkSum status:" + checkSum);
                    }
                    //适配配置信息
                    List<String> logs = new ArrayList<>();
                    JSONArray logArray = companyObject.optJSONArray("logs");
                    if (logArray != null && logArray.length() > 0) {
                        int len = logArray.length();
                        for (int i = 0; i < len; i++) {
                            String str = logArray.optString(i);
                            if (!TextUtils.isEmpty(str)) {
                                logs.add(str);
                            }
                        }
                    }
                    ConfigInfo configInfo = new ConfigInfo(companyId, token, uuid, mManagerServer, logs, encManagerServer);
                    XCloud2Map.getInstance().init(configInfo, validCount, mAppFilePath);
                    e.onNext(mResultData);
                } else {
                    e.onError(new XCloudException("接口数据异常,请联系管理员..."));
                }
            }
        }, BackpressureStrategy.BUFFER);
    }

    //使用登录的缓存数据，如果是缓存数据，则只初始化本地存在的适配包和运行时
    private Flowable<JSONObject> resultCacheDataFlowable() {
        return Flowable.create(new FlowableOnSubscribe<JSONObject>() {
            @Override
            public void subscribe(FlowableEmitter<JSONObject> e) throws Exception {
                JSONObject dataObject = mResultData.optJSONObject("data");
                JSONObject companyObject = null;
                if (dataObject != null) {
                    companyObject = dataObject.optJSONObject("company");
                }
                if (dataObject != null && companyObject != null) {
                    String companyId = companyObject.optString("companyId");
                    String token = dataObject.optString("deviceToken", "");
                    int validCount = dataObject.optInt("validCount", 0);
                    String uuid = dataObject.optString("uuid", "");
                    //适配配置信息
                    List<String> logs = new ArrayList<>();
                    JSONArray logArray = companyObject.optJSONArray("logs");
                    if (logArray != null && logArray.length() > 0) {
                        int len = logArray.length();
                        for (int i = 0; i < len; i++) {
                            String str = logArray.optString(i);
                            if (!TextUtils.isEmpty(str)) {
                                logs.add(str);
                            }
                        }
                    }
                    String encManagerServer = companyObject.optString("managerServer");
                    ConfigInfo configInfo = new ConfigInfo(companyId, token, uuid, mManagerServer, logs, encManagerServer);
                    XCloud2Map.getInstance().init(configInfo, validCount, mAppFilePath);
                    e.onNext(mResultData);
                } else {
                    e.onError(new XCloudException("接口数据异常,请联系管理员..."));
                }
            }
        }, BackpressureStrategy.BUFFER);
    }

    private boolean userLocalRuntime(JSONObject runtimeObj) throws Exception {
        if (BuildConfig.DEBUG) {
            final boolean isSpecificVersion = runtimeObj.optBoolean("isSpecificVersion");
            final String runtimeVersion = isSpecificVersion ? runtimeObj.optString("runtimeVersion") : runtimeObj.optString("primaryVersion");
            String localFileName = Environment.getExternalStorageDirectory().getPath() + File.separator + runtimeVersion + ".zip";
            File localFile = new File(localFileName);
            if (localFile.exists()) {
                String targetFileName = mAppFilePath + File.separator + ContentValues.APP_ENGINE_ROOT_PATH + File.separator + runtimeVersion;
                File targetFile = new File(targetFileName);
                if (!targetFile.exists()) {
                    boolean copySuccess = FileUtils.copyFile(localFileName, targetFile.getParent() + File.separator + runtimeVersion + ".zip");
                    if (copySuccess) {
                        boolean unZipSuccess = FileUtils.unZipRes(new File(targetFile.getParent() + File.separator + runtimeVersion + ".zip"));
                        FileUtils.deletePathReal(targetFile.getParent() + File.separator + runtimeVersion + ".zip");
                        if (unZipSuccess) {
                            return true;
                        }
                    }
                } else {
                    return true;
                }
            }
        }
        return false;
    }
}
